(
  function () {
    let upload_inp = document.querySelector('.progress2-files')
    let select = document.querySelector('.progress2-select')
    let info = document.querySelector('.progress2-info')
    let upload = document.querySelector('.progress2-upload')
    let sizeInfo = document.querySelector('.progress2-size')
    let files = []
    let status = Object.create(null)
    let defaultInfo = '请选择文件上传(小于1GB, 50个以内), 长按我清空文件列表'
    let size = 0

    upload_inp.addEventListener('change', function (e) {
      console.log(upload_inp.files)

      // 如果此时选择读取了文件,就直接不走if,继续在info里面加信息,并且生成files数组,否则,说明传入了文件的信息
      // 但是是空的，所以直接显示默认提示，return即可
      if (!upload_inp.files.length) {
        info.innerText = defaultInfo
        return
      }

      // 有文件进来了，清空info提示信息，开始加载，不可选择
      clear("")
      isUploading(true)


      // 过滤的文件列表
      let excludeList = []

      // 通过.files拿到所有选中的文件
      // 这是一个fileList的列表，原型先是File后世Blob，内部有很多属性和方法
      files = Array.from(upload_inp.files)
      console.log(files)


      files.forEach((item, index, arr) => {

        // 这里可以匹配格式, 不过这里直接全匹配, 可以改
        if ((/.*/).test(item.name)) {
          // 得到唯一的key，能够操作指定的文件信息
          let key = getUniqueKey()
          // 挂到files数组内的的每一个对象元素上
          arr[index].key = key

          info.innerHTML += `
          <li>
            <span key="${key}">${item.name}</span>
            <button class="remove remove-active remove-disabled">remove</button>
          </li>
            `

          // 计算并显示上传文件的大小
          size += item.size

          // 累计显示文件总大小
          sizeInfo.innerText = toSizeInfo(size)
        }
        else {
          // 对于不合适的格式----不会加入files里, 并加入排除的列表数组
          excludeList.push(item.name)

          // 去掉该文件对象
          arr.splice(index, index + 1)
        }
      })


      // 这里不用像base64写进分支,因为都是同步

      console.log(files)
      // 把不对的格式和大小不合格过滤或提示
      fileFilter(excludeList)

    })

    async function fileFilter(excludeList) {
      let length = upload_inp.files.length

      // 如果格式不一样，就会在if分支过滤, files数组的长度就不会等于upload_inp.files.length
      if (files.length !== length) {
        // 异步等待文件同步载入结束在进行
        await delay(0)
        alert(`格式已过滤！\n已排除\n${excludeList.join('\n')}`)
      }

      if (files.length) {

        // 限制大小同理-----一byte(字节)计数
        // 10 * 1024 * 1024表示10MB
        if (size > 1024 * 1024 * 1024) {
          // 异步等待文件同步载入结束在进行
          await delay(0)
          alert('文件总量须小于1GB!请删减')
          status.size = 'File too large'
        }
        else {
          await delay(0)
          alert('文件加载完毕')
        }
      }

      // 文件加载完毕，可以上传了
      isUploading(false)
    }


    // 利用事件委托: remove的button在info的div里,会冒泡,所以只要点击了remove的button,info的div也会被点击到
    // 此时只要对比target就行了
    // 什么时候使用事件委托呢?
    // 当有很多相同的事件需要监听的时候,比如这里的列表的button,如果每一个都监听,那么内存会给每一个监听器(含回调函数)都开辟空间
    // 在触发时回调,相当于一个方法拷贝了n份,而直接在父元素使用事件委托,就只有一个事件监听器,开销会小很多
    info.addEventListener('click', (e) => {

      // 移除
      if (e.target.className.includes('remove')) {
        let key = e.target.previousElementSibling.getAttribute('key')
        console.log(e.target.previousElementSibling.getAttribute('key'))
        files = files.filter(item => {
          // 如果匹配到删减的文件，就减去对应的大小，并且在判断是否小于了100MB，如果小于100MB就删除status.size，
          // 这样就点击upload判断时，就可以上传了
          if (item.key === key) {
            size -= item.size
            sizeInfo.innerText = toSizeInfo(size)
            // 不限制总量只限制每个文件的量
            size < 1024 * 1024 * 1024 && delete status.size
            console.log(item.name, size, status.size, files)
            e.target.parentElement.remove()
          }

          return !(item.key === key)
        })

        if (!files.length) {
          info.innerText = defaultInfo
        }
      }

    })

    // 利用定时器长按1秒清空
    let clearAll
    info.addEventListener('mousedown', (e) => {
      if (files.length) {
        clearAll = setTimeout(() => {
          clear(defaultInfo)
          delete status.size
        }, 1000)
      }
    })
    info.addEventListener('mouseup', (e) => {
      if (clearAll) {
        clearTimeout(clearAll)
        clearAll = null
      }
    })

    // 绑定选择事件
    console.log(handleSelect(select, upload_inp))

    upload.addEventListener('click', async function (e) {

      if (!upload.classList.contains('active') || !select.classList.contains('active')) {
        return
      }

      // 相当于防抖, 只要上传,只有上传之后才会可点击状态

      if (!files.length) {
        alert('上传文件为空, 请选择文件!')
      }
      else {

        // 如果文件太大，直接return，不上传
        if (status.size) {
          alert(status.size + ', please try again~')
          clear(defaultInfo)
          return;
        }

        isUploading(true)

        let removeBtns = info.querySelectorAll('.remove')

        let axioses = []

        // 开始上传进度全部为0%
        removeBtns.forEach((remove, index, arr) => {
          arr[index].innerText = '0%'
        })

        // 注意多文件上传使用formData的append遍历数组所有的元素来添加文件
        // 不用更改FileList直接Array.from转化FileList为array在改,此后直接用转化后的array上传就行了
        // 如下的files
        files.forEach((item, index) => {
          console.log(upload_inp.files)

          let formData = new FormData()
          files[index] && formData.append('files', files[index])
          formData.append('fqm', 'fqmyysjjd')

          // 所有的请求都完成了, 才会成功
          axioses.push(axios.post('/upload_formdata', formData, {
            Headers: {
              'Content-Type': 'multipart/form-data',
            },

            // axios的第三个参数,检测文件上传进度
            onUploadProgress(ev) {
              // console.log(ev)

              removeBtns.forEach((remove, index, arr) => {
                if (item.key == remove.previousElementSibling.getAttribute('key')) {
                  // console.log(((ev.loaded / ev.total) * 100).toString().replace(/\..*/, ''))
                  arr[index].innerText = ((ev.loaded / ev.total) * 100).toString().replace(/\..*/, '') + '%'
                }
              })

            }
          })
            .then(async (res) => {

              if (res.data.ok) {
                console.log(res.data.info.join('\n'))
                console.log('上传完毕~')

                removeBtns.forEach((remove, index, arr) => {
                  if (item.key == remove.previousElementSibling.getAttribute('key')) {
                    console.log('-----------')
                    arr[index].innerText = '100%'
                  }
                })

                // await delay(1000)

                // 有的时候直接上传完毕就直接刷新页面了, 已经直到原因了似乎是nodejs异步的promise响应就会刷新
                // alert(res.data.ok + '\n' + res.data.info.join('\n'))

                // debugger
              }
              else {
                throw res.data.info
              }

            }).catch(e => {
              // console.log(e)
              Promise.reject(e)
            })
          )

        })


        console.log(axioses)
        Promise.all(axioses).then(async (resList) => {

          // 如果promise的then不处理, 这里就可以拿到所有promise的then(resolve)返回数据的数组
          // 如果promise已经then了,这里all的then拿到的就是undefined
          // resList.forEach(res => {
          //   console.log(res.data.info.join('\n'))
          //   console.log('上传完毕~')
          // })

          console.log(resList)
          console.log('全部上传完毕~~')
          // debugger
          await delay(1000)
        }).catch(e => {
          console.log(e)
        }).finally(() => {
          isUploading(false)
          clear(defaultInfo)
        })

      }
    })


    // 上传时按钮禁用
    function isUploading(bool) {
      select.disabled = bool
      upload.disabled = bool
      if (bool) {
        select.classList.remove('active')
        upload.classList.remove('active')
        select.classList.add('file-bnt-disabled')
        upload.classList.add('file-bnt-disabled')

        document.querySelectorAll('.remove').forEach((item, index, arr) => {
          arr[index].disabled = bool
          arr[index].classList.remove('remove-active')
          arr[index].classList.add('remove-disabled')
        })
      }
      else {
        select.classList.add('active')
        upload.classList.add('active')
        select.classList.remove('file-bnt-disabled')
        upload.classList.remove('file-bnt-disabled')

        document.querySelectorAll('.remove').forEach((item, index, arr) => {
          arr[index].disabled = bool
          arr[index].classList.add('remove-active')
          arr[index].classList.remove('remove-disabled')
        })
      }
    }

    // 清除信息
    function clear(defaultInfo) {
      files = []
      info.innerText = defaultInfo
      size = 0
      sizeInfo.innerText = '0MB'
      status = Object.create(null)
    }

  }
)()